// noinspection JSUnusedGlobalSymbols

import { unref } from 'vue';
import { useWebSocket, UseWebSocketReturn } from '@vueuse/core';
import { getToken } from '/@/utils/auth';

let result: UseWebSocketReturn<any>;
const listeners = new Map();

/**
 * 开启 WebSocket 链接，全局只需执行一次
 * @param url
 */
export function connectWebSocket(url: string) {
  //update-begin-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端，存在性能和安全问题。 #3278
  const token = (getToken() || '') as string;
  result = useWebSocket(url, {
    // 自动重连 (遇到错误最多重复连接10次)
    autoReconnect: {
      retries: 10,
      delay: 5000,
    },
    // 心跳检测
    heartbeat: {
      message: JSON.stringify({ type: 'ping' }),
      // 如果服务器压力再改回来55秒
      interval: 55000,
    },
    protocols: [token],
  });
  //update-end-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端，存在性能和安全问题。 #3278
  if (result) {
    // modify by wangjie 此处设置无效，改为ws.onopen = onOpen; ws.onclose = onClose;
    // result.open = onOpen;
    // result.close = onClose;

    const ws = unref(result.ws);
    if (ws != null) {
      ws.onopen = onOpen;
      ws.onclose = onClose;
      ws.onerror = onError;
      ws.onmessage = onMessage;
    }
  }
}

function onOpen() {
  console.log('[WebSocket] 连接成功');
}

function onClose(e) {
  console.log('[WebSocket] 连接断开：', e);
}

function onError(e) {
  console.log('[WebSocket] 连接发生错误: ', e);
}

function onMessage(e) {
  console.debug('[WebSocket] -----接收消息-------', e.data);
  try {
    const data = JSON.parse(e.data);
    for (const label of listeners.keys()) {
      const lts = listeners.get(label);
      if (lts && lts.length) {
        try {
          lts.forEach((listener) => {
            // 扩展callback函数,让其拥有listener.vm中的方法
            listener.callback(data);
          });
        } catch (err) {
          console.error(err);
        }
      }
    }
  } catch (err) {
    console.error('[WebSocket] data解析失败：', err);
  }
}

/**
 * 添加 WebSocket 消息监听
 * @param label 事件名称
 * @param callback  回调函数
 */
export function onWebSocket(label: string, callback: (data: object) => any) {
  if (typeof callback === 'function') {
    // label不存在就添加
    if (!listeners.has(label)) {
      listeners.set(label, []);
      listeners.get(label).push({ callback: callback });
    }
  } else {
    console.debug('[WebSocket] 添加 WebSocket 消息监听失败：传入的参数不是一个方法');
  }
}

/**
 * 解除 WebSocket 消息监听
 * @param label 事件名称
 * @param callback  回调函数
 */
export function offWebSocket(label: string, callback: (data: object) => any) {
  // 从监听列表中获取当前事件
  const lts = listeners.get(label);
  let index;
  if (lts && lts.length) {
    // 寻找当前事件在事件监听列表的位置
    index = lts.reduce((i, listener, index) => {
      if (typeof listener.callback === 'function' && listener.callback === callback) {
        i = index;
      }
      return i;
    }, -1);

    if (index > -1) {
      // 移除事件
      lts.splice(index, 1);
      listeners.set(label, listeners);
      return true;
    }
  }
}

export function useMyWebSocket() {
  return result;
}
